import asyncio
import time

import aiohttp

from app_v2.bili_api.bvid import Bvid
from app_v2.bili_api.common import headers_with_cookie, cookie_
from app_v2.bili_api.mid import Mid


class ApiSession:
    def __init__(self, cookie: str):
        self._cookie = cookie
        self.session = None

    @staticmethod
    def default():
        return ApiSession("")

    async def __aenter__(self):
        self.session = aiohttp.ClientSession(headers=headers_with_cookie(self._cookie))
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        if self.session:
            await self.session.close()

    async def fetch_data(self, url, params=None):
        start_time = time.time()
        async with await self.session.get(url, params=params) as response:
            response.raise_for_status()
            data = await response.json()
        print(f"[ApiSession] fetch: {url} took {time.time() - start_time} seconds")
        return data

    async def get(self, url, params=None, headers=None):
        print("[WARNING] Use fetch_data() to make a difference")
        async with await self.session.get(url, params=params, headers=headers) as response:
            response.raise_for_status()
            return await response.json()

    def get_cookie(self) -> str:
        return self._cookie

    @staticmethod
    async def check_cookie(cookie: str) -> bool:
        try:
            await ApiSession.check_session_throws(cookie)
            return True
        except:
            return False

    @staticmethod
    async def check_session_throws(cookie: str):
        async with ApiSession(cookie) as session:
            await session.up(2).info()

    def update_cookie(self, cookie: str):
        self._cookie = cookie
        self.session.headers.update(headers_with_cookie(self._cookie))

    def up(self, mid: str | int) -> Mid:
        return Mid(mid, self)

    def video(self, bvid: str):
        return Bvid(bvid, self)

    async def me(self):
        url = "https://api.bilibili.com/x/member/web/account"
        resp = await self.fetch_data(url)
        return Mid(resp["data"]["mid"], self)

    @staticmethod
    def parse_cookie_string(cookie_str: str) -> dict:
        """将字符串格式的Cookie转换为字典"""
        cookies = {}
        for item in cookie_str.split(';'):
            item = item.strip()
            if not item:
                continue
            if '=' in item:
                key, value = item.split('=', 1)
                cookies[key.strip()] = value.strip()
            else:
                cookies[item] = ''
        return cookies

    async def search(self, keyword: str):
        url = "https://api.bilibili.com/x/web-interface/wbi/search/all/v2"
        resp = await self.fetch_data(url, params={"keyword": keyword})
        return resp["data"]["result"]


if __name__ == "__main__":
    async def test():
        async with ApiSession(cookie_) as session:
            await session.search("325")


    asyncio.run(test())
